{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Hy Lisp\n", "\n", "Examples of Lisp, and discussion of video of final project\n", "\n", "How does Common Lisp differ from Scheme? Typically:\n", "\n", "* Lisp often has Dynamic Scope vs. Scheme always has Lexical Scope \n", "* Syntax differences (Lisp has defn vs. Scheme's define ... (lambda ...)) \n", "* Lisp is large and unwieldy\n", "* Scheme is and elegant\n", "* Lisp is practical\n", "* Scheme is beautiful\n", "* Lisp uses nil for \"empty list\"; it is also false\n", "* Scheme uses '() for \"empty list\"; only #f is false\n", "* Lisp uses different scopes for variables and functions !?\n", "\n", "How does Hy Lisp differ from Common Lisp?\n", "\n", "* Hy Lisp has Python's scoping rules, lexically scoped ... sorta\n", "* Hy Lisp is really just Python with different syntax\n", "* Hy Lisp uses Python's stack for function calls --- no trampoline, or Tail Call Elimination, etc.\n", "* Hy Lisp has Lisp-if and Python-if\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Videos and Blogs\n", "\n", "1. http://technicae.cogitat.io/2014/11/scientific-computing-with-hy.html - Hy computing\n", "1. http://nbviewer.ipython.org/github/bollwyvl/hy_kernel/blob/master/notebooks/Tutorial.ipynb - Hy notebook\n", "1. https://www.youtube.com/watch?v=E7hTimGmGBs - Hy video\n", "2. https://www.youtube.com/watch?v=P76Vbsk_3J0 - Clojure video\n", "3. https://www.youtube.com/watch?v=0Vq2rcjWbTc - Animvs video\n", "\n", "## Final Project + Video Rubric\n", "\n", "* Quality - 20%\n", "* Programming Languages integration - connection to PL ideas, such as scope, continuations, internals, closures, parser, lexer, interpreter, etc. - 20%\n", "* Introduction to new language - 20%\n", "* Code and documentation effort - 20%\n", "* Conversation on videos - 20%\n", "\n", "**Bonus**: up to 10%, examples:\n", "\n", "* creativity\n", "* effective use of media (eg, animations, varied video sequences)\n", "* extensive docs, code integration\n", "\n", "**Due**: Monday, Dec 15, 2014 8am\n", "\n", "Notebook on Hy Lisp:\n", "\n", "http://nbviewer.ipython.org/github/bollwyvl/hy_kernel/blob/master/notebooks/Tutorial.ipynb\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created file '/home/dblank/.ipython/kernels/hy/kernel.json'.\n" ] } ], "source": [ "%%file ~/.ipython/kernels/hy/kernel.json\n", "\n", "{\n", " \"argv\": [\"python\", \"-m\", \"hy_kernel.hy_kernel\", \"-f\", \"{connection_file}\"],\n", " \"display_name\": \"Hy Lisp\",\n", " \"language\": \"hy\",\n", " \"codemirror_mode\": \"hy\",\n", " \"language_info\": {\n", " \"name\": \"hy\",\n", " \"codemirror_mode\": {\n", " \"name\": \"hy\"\n", " },\n", " \"mimetype\": \"text/x-hylang\",\n", " \"pygments_lexer\": \"ipython3\"\n", " },\n", " \"help_links\": [\n", " {\n", " \"text\": \"Hy Documentation\",\n", " \"link\": \"http://docs.hylang.org/\"\n", " },\n", " {\n", " \"text\": \"Hy Google Group\",\n", " \"link\": \"https://groups.google.com/forum/#!forum/hylang-discuss\"\n", " },\n", " {\n", " \"text\": \"Hy Github\",\n", " \"link\": \"https://github.com/hylang/hy\"\n", " }\n", " ]\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lisp" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "(defn simple-conversation ()\n", " (print \"Hello! I'd like to get to know you. Tell me about yourself!\")\n", " (setv name (raw_input \"What is your name? \"))\n", " (setv age (raw_input \"What is your age? \"))\n", " (print (+ \"Hello \" name \"! I see you are \"\n", " age \" years old.\"))\n", " None)\n", "\n", "(simple-conversation)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "(defn fact (n)\n", " (if (= n 1)\n", " 1\n", " (* n (fact (- n 1)))))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "120L" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(fact 5)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "6L" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "((let [[x 5]] \n", " (lambda () (+ x 1))))" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "67526802209645841583879061361800814224269427869589384312198268703685091643180416969132446952698303794226010370578672908593198347699886928591906501031587651846976759681112609524787093848004428636186893395272784450630354080243217646658024696659065951793757223520229235577548653833681102170973893746054649126415909143150172860721156685810655759230011450132992176454983227538696340112610447029002337004887877266387704586077293585433151612518800147764461182680822867092786694982831838641800997499819339206579415325649748486265233918911087114592440896594062675914294925816719862178374679272092637524786939036290035924271782253738059886933923447877769583003016705363339031413069155837518524761078342052635475632113169618774549275701480106933362990003732589370593557325299434734459295866728988740794174654391479926000848846686708729736713207285203712732201272410830836913052635365082888725171636081587151603468291106754640398232146673627370895934090777828827549554232436190464827998683927179246029919443251026464452337939599198528297828591122689960620361238248313158071643395848405047261412680039877733761849874447323867911712630023171745968278465780558568067035013885275080292137360491875164947724464221693533755035300065350065137490832039523382963747026185653050331832380991844842560750923543775188582096487476950254418365198999674684417286265442786651594404781622946901879166382930714196908227460133027605817864877377712193142137625430353718448269390732615776645283198828602917680224041088993892610506802195917247838900106910698057030379190571057605849323113308634452008179881165616449767648354161225066967961297609698742737923389391615207441152319392845687673311899247085327703421862972871644495409572259985563215471482083325653231777113271326579970310755604973969708949477374254974480294652427022436705380184064008853457214518515270985563195412993145274057688634448812449445800617631162768243125606424844709372022149908463572254912654907763445758543980999149122998104378965626781898655221443263601405152073199706585080288735040205417371277253096243200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n" ] } ], "source": [ "(defn display (v) (print v) 'ok)\n", "(try\n", " (display (fact 900))\n", " (catch [e Exception] 'ok)\n", ";; (else (print \"no errors\"))\n", " (finally 'ok)\n", " )" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": true }, "outputs": [], "source": [ "(defn display (v) (print v) 'ok)\n", "(try\n", " (display (fact 1000))\n", " (catch [e Exception] 'ok)\n", ";; (else (print \"no errors\"))\n", " (finally 'ok)\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cool Macro tricks\n", "\n", "### \"Threading Macro\" from Clojure" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sh` is a Python library that wraps up shell commands as Python functions.\n", "\n", "* cat - concatenate \n", "* grep - search\n", "* wc - word/character/line count\n", "\n", "In Python, you would write:\n", "\n", "```python\n", "from sh import cat, grep, wc\n", "\n", "wc(grep(cat(\"/usr/share/dict/words\"), \"-E\", \"^hy\"), \"-l\")\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### In Hy Lisp:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [], "source": [ "(import [sh [cat grep wc]])" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "210" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(wc (grep (cat \"/usr/share/dict/words\") \"-E\" \"^hy\") \"-l\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "210" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(-> (cat \"/usr/share/dict/words\") (grep \"-E\" \"^hy\") (wc \"-l\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## How is Hy implemented?\n", "\n", "From hy_kernel.py:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "class HyKernel(IPythonKernel):\n", " def do_execute(self, code, *args, **kwargs):\n", " ''' \n", " Generate python code, and have IPythonKernel run it, or show why we \n", " couldn't have python code. \n", " '''\n", " try:\n", " tokens = tokenize(code)\n", " _ast = hy_compile(tokens, '__console__', root=ast.Interactive)\n", " _ast_for_print = ast.Module()\n", " _ast_for_print.body = _ast.body\n", " code = astor.codegen.to_source(_ast_for_print)\n", " except Exception as err:\n", " if (not hasattr(err, 'source')) or not err.source:\n", " err.source = code\n", " # shell will find the last exception \n", " self.shell.showsyntaxerror()\n", " # an empty code cell is basically a no-op \n", " code = ''\n", " return super(HyKernel, self).do_execute(code, *args, **kwargs)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Macros\n", "\n", "### Hy Philosophy:\n", "\n", "```\n", "(defmacro -> [head &rest rest]\n", " (setv ret head)\n", " (for* [node rest]\n", " (if (not (isinstance node HyExpression))\n", " (setv node `(~node)))\n", " (.insert node 1 ret)\n", " (setv ret node))\n", " ret)\n", " ```\n", " \n", " ### Scheme Philosophy\n", " \n", " ```\n", " (define-syntax ->\n", " [(-> ?a) ?a] \n", " [(-> ?a (?b . ?args) . ?rest)\n", " (-> (?b ?a . ?args) . ?rest)])\n", " ```" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'HELLO!'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(-> '\"hello\" (+ \"!\") .upper str)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Calysto Scheme 2", "language": "scheme", "name": "calysto_scheme" }, "language_info": { "codemirror_mode": { "name": "scheme" }, "mimetype": "text/x-scheme", "name": "scheme", "pygments_lexer": "scheme" } }, "nbformat": 4, "nbformat_minor": 0 }